package com.xxm.audio

import android.annotation.SuppressLint
import android.app.Application
import android.media.AudioAttributes
import android.media.AudioFormat
import android.media.AudioRecord
import android.media.AudioTrack
import android.media.MediaRecorder
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream

/**
 *Time:2023/5/12
 *Author:zhangwenshuan
 *Description:
 *since version
 *
 */
@SuppressLint("MissingPermission")

class AudioModel(application: Application) : AndroidViewModel(application) {
    private val TAG = "AudioModel"

    private  var audioRecord: AudioRecord?=null

    private val sampleRate = 44100

    private var isRecording = false

    private var bufferSize = 0

    var size = MutableLiveData<Long>(0)

    var filePaths=MutableLiveData<MutableList<AudioItem>>()


    fun initBuffer(){
        bufferSize = AudioRecord.getMinBufferSize(
            sampleRate, //采样
            AudioFormat.CHANNEL_IN_MONO, //声道
            AudioFormat.ENCODING_PCM_16BIT //编码
        )
    }

    private fun createAudioRecord() {
        Log.d(TAG, "最小缓冲区大小:${bufferSize}")
        audioRecord = AudioRecord(
            MediaRecorder.AudioSource.MIC,
            sampleRate,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            bufferSize
        )
        Log.d(TAG, "audioRecord:${audioRecord}")
    }

    fun startRecord() {
        if (isRecording) return
        isRecording = true
        createAudioRecord()
        audioRecord!!.startRecording()
        Log.d(TAG, "state:${audioRecord!!.recordingState}")
        viewModelScope.launch(Dispatchers.IO) {
            val buffer = ByteArray(bufferSize)
            val file = getApplication<Application>().applicationContext.externalCacheDir
            val saveFile = File(file, "audio_${System.currentTimeMillis()}.pcm")
            Log.d(TAG, "path:${saveFile.absolutePath}")
            if (!saveFile.exists()) saveFile.createNewFile()
            val fileOutputStream = FileOutputStream(saveFile)
            while (isRecording) {
                var read = audioRecord!!.read(buffer, 0, bufferSize)
                Log.d(TAG, "result:${read}")
                withContext(Dispatchers.Main) {
                    size.value = size.value!!+ bufferSize
                }
                if (read != AudioRecord.ERROR_INVALID_OPERATION) {
                    fileOutputStream.write(buffer)
                }
            }
            fileOutputStream.close()
        }
    }

    fun stopRecord() {
        isRecording = false
       release()
        getAudioFile()
    }


    private var audioTrack: AudioTrack? = null

    private fun createAudioTrack() {
        audioTrack = AudioTrack.Builder()
            .setAudioAttributes(
                AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build()
            )
            .setAudioFormat(
                AudioFormat.Builder()
                    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                    .setSampleRate(sampleRate)
                    .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                    .build()
            )
            .setBufferSizeInBytes(bufferSize)
            .build()
    }

    private var isPlaying = false
    fun startPlay(path: String) {
        if (isPlaying) return
        val sourceFile = File(path)
        if (sourceFile.exists()) {
            isPlaying = true
           viewModelScope.launch(Dispatchers.IO) {
               createAudioTrack()
               audioTrack!!.play()
               val fileInputStream = FileInputStream(sourceFile)
               val buffer = ByteArray(bufferSize)

               while (isPlaying) {
                   val size = fileInputStream.read(buffer, 0, bufferSize)
                   if (size <= 0) {
                       release()
                       isPlaying = false
                       continue
                   }
                   audioTrack!!.write(buffer, 0, bufferSize)
               }
           }
        }
    }

     fun release() {
         isPlaying=false
         isRecording=false
        audioRecord?.stop()
        audioRecord?.release()
        audioRecord=null
        audioTrack?.stop()
        audioTrack?.release()
        audioTrack = null
    }

    fun stopPlay() {
        isPlaying=false
    }

    fun getAudioFile() {
       val dictory= getApplication<Application>().applicationContext.externalCacheDir
        if(dictory?.isDirectory==true){
            val list= mutableListOf<AudioItem>()
            dictory.listFiles().forEach {
                if(it.name.endsWith(".pcm")){
                    list.add(AudioItem(it.absolutePath))
                }
            }
            filePaths.value=list
        }
    }
}